package cn.edu.xhu.library_management.area.service.impl;

import cn.edu.xhu.library_management.area.entity.LmArea;
import cn.edu.xhu.library_management.area.entity.LmFloor;
import cn.edu.xhu.library_management.area.entity.LmItemNum;
import cn.edu.xhu.library_management.area.entity.dto.LmAreaDTO;
import cn.edu.xhu.library_management.area.entity.search.LmAreaSearch;
import cn.edu.xhu.library_management.area.entity.vo.LmAreaVo;
import cn.edu.xhu.library_management.area.mapper.AreaMapper;
import cn.edu.xhu.library_management.area.mapper.FloorMapper;
import cn.edu.xhu.library_management.area.mapper.ItemNumMapper;
import cn.edu.xhu.library_management.area.service.AreaService;
import cn.edu.xhu.library_management.common.entity.ItemType;
import cn.edu.xhu.library_management.common.entity.ResultCode;
import cn.edu.xhu.library_management.common.exception.LibraryManagementException;
import com.fasterxml.jackson.databind.util.BeanUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: MMJ
 * @Date: 2022 - 11 - 14
 * @Description:
 */
@Service
public class AreaServiceImpl implements AreaService {
    @Resource
    private AreaMapper areaMapper;
    @Resource
    private FloorMapper floorMapper;

    @Resource
    private ItemNumMapper itemNumMapper;

    @Override
    public List<LmArea> findAreasByFloorId(Integer FloorId) {
        return areaMapper.findAreasByFloorId(FloorId);
    }

    @Override
    public List<LmAreaVo> findAreasByInfoId(Integer InfoId) {
        List<LmAreaVo> list = new ArrayList<>();
        List<LmFloor> floors = floorMapper.findFloorsByInfoId(InfoId);
        floors.forEach(floor -> {

            List<LmArea> areas = areaMapper.findAreasByFloorId(floor.getId());
            if (areas.size() == 0) {
                return;
            }
            areas.forEach(area -> {
                LmAreaVo vo = new LmAreaVo();
                BeanUtils.copyProperties(area, vo);
                vo.setIndex(floor.getIndex());
                list.add(vo);
            });

        });

        // 排序 楼层 升序 编号 升序
        return sort(list);
    }

    private List<LmAreaVo> sort(List<LmAreaVo> list) {
        // 排序 楼层 升序 编号 升序
        return list.stream().sorted(Comparator.comparing(LmAreaVo::getIndex).thenComparing(LmAreaVo::getNumber)).collect(Collectors.toList());
    }

    @Override
    public LmArea findAreaById(Integer id) {
        return areaMapper.findAreaById(id);
    }
/*
@ApiModelProperty(value = "区域类型(1 书架，2 座位)")
    private Integer type;

    private Character number;

    private Integer remainCapacity;

    private Integer totalCapacity;

    private Integer floorId;

    private Integer infoId;
* */
    @Override
    public List<LmAreaVo> search(LmAreaSearch search) {
        return areaMapper.search(search);

    }

    public LmArea findAreaByNumberAndFloorId(@Param("number") char number, @Param("floorId") Integer floorId) {
        return areaMapper.findAreaByNumberAndFloorId(number, floorId);
    }

    @Transactional // TODO 事务
    @Override
    public boolean addArea(LmAreaDTO areaDTO) {
        // 判断楼层id是否存在 区域是否重复
        areaDTO.setId(null);
        judgeFloorIDAndNumber(areaDTO);
        areaDTO.setRemainCapacity(areaDTO.getTotalCapacity());
        int resArea = areaMapper.addArea(areaDTO);
        int resItemNum = 0;
        // 添加数量
        if (areaDTO.getType() != ItemType.OTHER.getCode()) {
            LmArea area = findAreaByNumberAndFloorId(areaDTO.getNumber(), areaDTO.getFloorId());
            resItemNum = itemNumMapper.addItemNum(new LmItemNum(null, areaDTO.getRows(), areaDTO.getColumns(), area.getId()));
            return resArea > 0 && resItemNum > 0;
        }
        return resArea > 0;
    }

    @Transactional // TODO 事务
    @Override
    public boolean updateArea(LmAreaDTO areaDTO) {
        // 判断楼层id是否存在 区域是否重复
        judgeFloorIDAndNumber(areaDTO);
//        int resArea = areaMapper.updateArea(areaDTO);
        int resItemNum = 0;

        LmArea area = areaMapper.findAreaById(areaDTO.getId());


        // 修改前类型为 其他 类型
        if (area.getType() == ItemType.OTHER.getCode()) {
            // 修改前类型为 其他 类型 现在修改为 书桌 座位类型
            if (areaDTO.getType() != ItemType.OTHER.getCode()) {
                int resItem = itemNumMapper.addItemNum(new LmItemNum(null, areaDTO.getRows(), areaDTO.getColumns(), areaDTO.getId()));
                int resArea = areaMapper.updateArea(areaDTO);
                return resArea > 0 && resItem > 0;
            } else {
                // 修改前类型为 其他 类型 现在修改也为 其他 类型
                int resArea = areaMapper.updateArea(areaDTO);
                return resArea > 0;
            }
        } else {
            // 修改前类型为 非其他 类型 现在修改为 其他 类型
            if (areaDTO.getType() == ItemType.OTHER.getCode()) {
                // 查询物品数量对象
                LmItemNum itemNum = itemNumMapper.findItemNumByAreaId(area.getId());
                int resItem = itemNumMapper.deleteItemNumById(itemNum.getId());
                int resArea = areaMapper.updateArea(areaDTO);
                return resArea > 0 && resItem > 0;
            } else {
                // 修改前类型为 非其他 类型 现在修改为 非其他 类型
                LmItemNum itemNum = itemNumMapper.findItemNumByAreaId(area.getId());
                int resItem = itemNumMapper.updateItemNum(new LmItemNum(itemNum.getId(), areaDTO.getRows(), areaDTO.getColumns(), areaDTO.getId()));
                int resArea = areaMapper.updateArea(areaDTO);
                return resArea > 0 && resItem > 0;
            }
        }


    }

    @Override
    public boolean deleteAreaById(Integer id) {
        return areaMapper.deleteAreaById(id) > 0;
    }

    @Override
    public List<LmArea> findAreasByType(Integer floorId, Integer type) {
        List<LmArea> lmAreaList = findAreasByFloorId(floorId);
        List<LmArea> areas = new ArrayList<>();
        lmAreaList.forEach(area -> {
            if (area.getType().equals(type)){
                areas.add(area);
            }
        });
        return areas;
    }

    /**
     * 判断 楼层id是否存在 区域是否重复
     *
     * @param area 区域对象
     */
    private void judgeFloorIDAndNumber(LmArea area) {
        // 判断区域是否存在
        if (area.getId() != null) {
            LmArea areaById = areaMapper.findAreaById(area.getId());
            if (areaById == null) {
                throw new LibraryManagementException(ResultCode.OPERATION_ERROR, "该区域不存在");
            }
        }
        // 查询楼层ID是否存在
        LmFloor floor = floorMapper.findFloorById(area.getFloorId());
        if (floor == null) {
            throw new LibraryManagementException(ResultCode.OPERATION_ERROR, "楼层不存在");
        }
        // 判断编号是否重复
        List<LmArea> areas = areaMapper.findAreasByFloorId(area.getFloorId());
        LmArea lmArea = areas.stream().filter(a1 -> a1.getNumber() == area.getNumber()).findFirst().orElse(null);
        if (lmArea != null) {
            if (area.getId() == null) {
                throw new LibraryManagementException(ResultCode.OPERATION_ERROR, "该楼层的该区域信息已经存在");
            }
            if (
                    lmArea.getType().equals(area.getType()) &&
                            lmArea.getTotalCapacity().equals(area.getTotalCapacity()) &&
                            lmArea.getRemainCapacity().equals(area.getRemainCapacity())
            ) {
                throw new LibraryManagementException(ResultCode.OPERATION_ERROR, "该楼层的该区域信息已经存在");
            }

        }
    }
}
